﻿using System;
using Xunit;
using Xunit.Should;

namespace Adjunct.Framework
{
	public class SemanticVersionSpec
	{
		[Fact]
		public void Invalid1Part()
		{
			InvalidateSemVer("1");
		}

		[Fact]
		public void Valid2Part()
		{
			ValidateSemVer("1.0", "1.0.0.0", string.Empty, int.MaxValue);
		}

		[Fact]
		public void Valid2PartWithPrerelease()
		{
			ValidateSemVer("1.0-alpha", "1.0.0.0", "alpha", int.MaxValue);
		}

		[Fact]
		public void Valid2PartWithPrereleaseAndBuild()
		{
			ValidateSemVer("1.0-alpha~1", "1.0.0.0", "alpha", 1);
			ValidateSemVer("1.0-alpha~01", "1.0.0.0", "alpha", 1);
		}

		[Fact]
		public void Valid3Part()
		{
			ValidateSemVer("1.0.0", "1.0.0.0", string.Empty, int.MaxValue);
		}

		[Fact]
		public void Valid3PartWithPrerelease()
		{
			ValidateSemVer("1.0.0-alpha", "1.0.0.0", "alpha", int.MaxValue);
		}

		[Fact]
		public void Valid3PartWithPrereleaseAndBuild()
		{
			ValidateSemVer("1.0.0-alpha~1", "1.0.0.0", "alpha", 1);
		}

		[Fact]
		public void Valid4Part()
		{
			ValidateSemVer("1.0.0.0", "1.0.0.0", string.Empty, int.MaxValue);
		}

		[Fact]
		public void Comparisons()
		{
			new SemanticVersion("1.0").CompareTo(new SemanticVersion("1.0.0")).ShouldEqual(0);
			new SemanticVersion("1.1").CompareTo(new SemanticVersion("1.0.0")).ShouldEqual(1);
			new SemanticVersion("1.2").CompareTo(new SemanticVersion("1.2.1")).ShouldEqual(-1);
			new SemanticVersion("2.0").CompareTo(new SemanticVersion("2.0.0-alpha")).ShouldEqual(1);
			new SemanticVersion("2.1").CompareTo(new SemanticVersion("2.1.1-alpha")).ShouldEqual(-1);
			new SemanticVersion("3.0-alpha").CompareTo(new SemanticVersion("3.0.0-alpha")).ShouldEqual(0);
			new SemanticVersion("3.1-alpha").CompareTo(new SemanticVersion("3.1.0-beta")).ShouldEqual(-1);
			new SemanticVersion("3.2-alpha").CompareTo(new SemanticVersion("3.2.0-Alpha")).ShouldEqual(32);
			new SemanticVersion("4.0-alpha").CompareTo(new SemanticVersion("4.0.0-alpha~1")).ShouldEqual(1);
			new SemanticVersion("4.1-alpha").CompareTo(new SemanticVersion("4.1.0-alpha~001")).ShouldEqual(1);
			new SemanticVersion("4.2-alpha").CompareTo(new SemanticVersion("4.1.1-alpha~1")).ShouldEqual(1);
			new SemanticVersion("4.3-alpha").CompareTo(new SemanticVersion("4.3.1-alpha~1")).ShouldEqual(-1);
			new SemanticVersion("4.4-alpha1").CompareTo(new SemanticVersion("4.4.0-alpha~1")).ShouldEqual(49);
			new SemanticVersion("5.0-alpha~1").CompareTo(new SemanticVersion("5.0.0-alpha~1")).ShouldEqual(0);
			new SemanticVersion("5.0-alpha~1").CompareTo(new SemanticVersion("5.0.0-alpha~001")).ShouldEqual(0);
			new SemanticVersion("5.0-alpha~1").CompareTo(new SemanticVersion("5.0.0-alpha~2")).ShouldEqual(-1);
			new SemanticVersion("5.0-alpha~2").CompareTo(new SemanticVersion("5.0.0-alpha~001")).ShouldEqual(1);
		}

		private static void InvalidateSemVer(string semVer)
		{
			Assert.Throws<Exception>(() => new SemanticVersion(semVer));
		}

		private static void ValidateSemVer(string semVer, string version, string preRelease, int build)
		{
			SemanticVersion valid = new SemanticVersion(semVer);
			valid.Version.ShouldEqual(new Version(version));
			valid.PreReleaseTag.ShouldEqual(preRelease);
			valid.Build.ShouldEqual(build);
		}
	}
}